package stream;

import lambda.cart.CartService;
import lambda.cart.Sku;
import lambda.cart.SkuCategoryEnum;
import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.OptionalDouble;

/**
 * 演示流的各种操作
 * @author zhaowenxu
 * @date 2020/4/7 0:02
 */
public class StreamOperator {

    List<Sku> list;

    @Before
    public void init() {
        list = CartService.getCartSkuList();
    }

    /**
     * filter的使用，过滤掉不符合断言判断的数据
     */
    @Test
    public void filterTest() {
        list.stream()
                .filter(sku -> SkuCategoryEnum.BOOKS.equals(sku.getSkuCategory()))
                .forEach(System.out::println);
    }

    /**
     * map的使用,将一个元素转换成另一个元素
     */
    @Test
    public void mapTest() {
        list.stream()
                .map(Sku::getSkuName)
                .forEach(System.out::println);
    }

    /**
     * flatMap使用：将一个对象转换成流
     */
    @Test
    public void flatMapTest() {
        list.stream()
                .flatMap(sku -> Arrays.stream(sku.getSkuName().split("")))
                .forEach(System.out::println);
    }

    /**
     * peek的使用：
     * peek和forEach很像，都是循环流中的元素，
     * 但是peek属于中间操作，遍历完流还可以使用
     * forEach属于终端操作，遍历完流不能被使用
     */
    @Test
    public void peekTest() {
        list.stream()
                .peek(sku -> System.out.println(sku.getSkuName()))
                .forEach(System.out::println);
    }

    /**
     * sort的使用，对流中元素进行排序，可选自然排序或指定排序规则
     */
    @Test
    public void sortTest() {
        list.stream()
                .sorted(Comparator.comparing(Sku::getTotalPrice))
                .forEach(System.out::println);
    }

    /**
     * distinct的使用，对流元素进行去重。有状态流操作
     *
     */
    @Test
    public void distinctTest() {
        list.stream()
                .map(Sku::getSkuCategory)
                .distinct()
                .forEach(System.out::println);
    }

    /**
     * skip使用，跳过前N条记录，有状态操作
     */
    @Test
    public void skipTest() {
        list.stream()
                .sorted(Comparator.comparing(Sku::getTotalPrice))
                .skip(3)
                .forEach(System.out::println);
    }

    /**
     * limit使用，截断前N条数据
     */
    @Test
    public void limitTest() {
        list.stream()
                .sorted(Comparator.comparing(Sku::getTotalPrice).reversed())
                .limit(3)
                .forEach(System.out::println);
        // skip和limit使用可以实现简单的分页操作
        // skip是跳过数据，limit是获取数据
        list.stream()
                .sorted(Comparator.comparing(Sku::getTotalPrice).reversed())
                .skip(0 * 3)
                .limit(3)
                .forEach(System.out::println);
    }

    /**
     * allMatch使用，终端操作，短路操作
     * 所有元素匹配返回true
     */
    @Test
    public void allMatchTest() {
        boolean match = list.stream()
                .peek(System.out::println)
                .allMatch(sku -> sku.getTotalPrice() > 100);
        System.out.println("match = " + match);
    }

    /**
     * anyMatch使用：任何元素匹配，返回true
     */
    @Test
    public void anyMatchTest() {
        boolean match = list.stream()
                .peek(System.out::println)
                .anyMatch(sku -> sku.getTotalPrice() > 100);
        System.out.println("match = " + match);
    }

    /**
     * noneMatch使用：任何元素都不匹配，返回true
     */
    @Test
    public void noneMatch() {
        boolean match = list.stream()
                .peek(System.out::println)
                .noneMatch(sku -> sku.getTotalPrice() > 10000);
        System.out.println("match = " + match);
    }

    /**
     * 找到第一个
     */
    @Test
    public void findFirstTest() {
        Optional<Sku> optional = list.stream()
                .findFirst();
        System.out.println(optional.get());
    }

    /**
     * 找到任意一个
     */
    @Test
    public void findAnyTest() {
        Optional<Sku> optional = list.stream()
                .findAny();
        System.out.println(optional.get());
    }

    /**
     * max使用
     */
    @Test
    public void maxTest() {
        OptionalDouble totalPrice = list.stream()
                // 获取总价
                .mapToDouble(Sku::getTotalPrice)
                .max();
        System.out.println(totalPrice);
    }

    @Test
    public void minTest() {
        OptionalDouble totalPrice = list.stream()
                // 获取总价
                .mapToDouble(Sku::getTotalPrice)
                .min();
        System.out.println(totalPrice);
    }

    @Test
    public void countTest() {
        long count = list.stream().count();
        System.out.println(count);
    }

}
